package com.jorado.core;

import java.util.concurrent.TimeUnit;

/**
 * @Auther: len.zhang
 * @Date: 2019/9/23 21:13
 * @Description:
 */
public class RTimer {
    public static final int STARTED = 0;
    public static final int STOPPED = 1;
    public static final int PAUSED = 2;
    protected int state;
    private TimerImpl timerImpl;
    private double time;
    private double culmTime;

    protected TimerImpl newTimerImpl() {
        return new NanoTimeTimerImpl();
    }

    public RTimer() {
        this.time = 0.0;
        this.culmTime = 0.0;
        (this.timerImpl = this.newTimerImpl()).start();
        this.state = 0;
    }

    public double stop() {
        assert this.state == 2;
        this.time = this.culmTime;
        if (this.state == 0) {
            this.time += this.timerImpl.elapsed();
        }
        this.state = 1;
        return this.time;
    }

    public void pause() {
        assert this.state == 0;
        this.culmTime += this.timerImpl.elapsed();
        this.state = 2;
    }

    public void resume() {
        if (this.state == 0) {
            return;
        }
        assert this.state == 2;
        this.state = 0;
        this.timerImpl.start();
    }

    public double getTime() {
        if (this.state == 1) {
            return this.time;
        }
        if (this.state == 2) {
            return this.culmTime;
        }
        assert this.state == 0;
        return this.culmTime + this.timerImpl.elapsed();
    }

    public static RTimer ofTimer() {
        return new RTimer();
    }

    private static class NanoTimeTimerImpl implements TimerImpl {
        private long start;

        @Override
        public void start() {
            this.start = System.nanoTime();
        }

        @Override
        public double elapsed() {
            return (double) TimeUnit.MILLISECONDS.convert(System.nanoTime() - this.start, TimeUnit.NANOSECONDS);
        }
    }

    protected interface TimerImpl {
        void start();

        double elapsed();
    }
}